package com.zl.learning.json.gson;

import com.google.gson.*;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.*;

public class GsonTest {
    public static class GsonTest1 {

        public static void main(String[] args) {
            Gson gson = new Gson();

            Student student1 = new Student();
            student1.setId(1);
            student1.setName("李坤");
            student1.setBirthDay(new Date());

            // //////////////////////////////////////////////////////////
            System.out.println("----------简单对象之间的转化-------------");
            // 简单的bean转为json
            String s1 = gson.toJson(student1);
            System.out.println("简单Bean转化为Json===" + s1);

            // json转为简单Bean
            Student student = gson.fromJson(s1, Student.class);
            System.out.println("Json转为简单Bean===" + student);
            // 结果:
            // 简单Bean转化为Json==={"id":1,"name":"李坤","birthDay":"Jun 22, 2012 8:27:52 AM"}
            // Json转为简单Bean===Student [birthDay=Fri Jun 22 08:27:52 CST 2012, id=1,
            // name=李坤]
            // //////////////////////////////////////////////////////////

            Student student2 = new Student();
            student2.setId(2);
            student2.setName("曹贵生");
            student2.setBirthDay(new Date());

            Student student3 = new Student();
            student3.setId(3);
            student3.setName("柳波");
            student3.setBirthDay(new Date());

            List<Student> list = new ArrayList<Student>();
            list.add(student1);
            list.add(student2);
            list.add(student3);

            System.out.println("----------带泛型的List之间的转化-------------");
            // 带泛型的list转化为json
            String s2 = gson.toJson(list);
            System.out.println("带泛型的list转化为json==" + s2);

            // json转为带泛型的list
            List<Student> retList = gson.fromJson(s2, new TypeToken<List<Student>>() {
            }.getType());
            for (Student stu : retList) {
                System.out.println(stu);
            }

            // 结果:
            // 带泛型的list转化为json==[{"id":1,"name":"李坤","birthDay":"Jun 22, 2012 8:28:52 AM"},{"id":2,"name":"曹贵生","birthDay":"Jun 22, 2012 8:28:52 AM"},{"id":3,"name":"柳波","birthDay":"Jun 22, 2012 8:28:52 AM"}]
            // Student [birthDay=Fri Jun 22 08:28:52 CST 2012, id=1, name=李坤]
            // Student [birthDay=Fri Jun 22 08:28:52 CST 2012, id=2, name=曹贵生]
            // Student [birthDay=Fri Jun 22 08:28:52 CST 2012, id=3, name=柳波]
        }
    }

    public static class GsonTest2 {

        public static void main(String[] args) {
            //注意这里的Gson的构建方式为GsonBuilder,区别于test1中的Gson gson = new Gson();
            Gson gson = new GsonBuilder()
                    .excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
                    .enableComplexMapKeySerialization() //支持Map的key为复杂对象的形式
                    .serializeNulls().setDateFormat("yyyy-MM-dd HH:mm:ss")//时间转化为特定格式
                    .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)//会把字段首字母大写,注:对于实体上使用了@SerializedName注解的不会生效.
                    .setPrettyPrinting() //对json结果格式化.
                    .setVersion(1.0)    //有的字段不是一开始就有的,会随着版本的升级添加进来,那么在进行序列化和返序列化的时候就会根据版本号来选择是否要序列化.
                    //@Since(版本号)能完美地实现这个功能.还的字段可能,随着版本的升级而删除,那么
                    //@Until(版本号)也能实现这个功能,GsonBuilder.setVersion(double)方法需要调用.
                    .create();



            Student student1 = new Student();
            student1.setId(1);
            student1.setName("李坤");
            student1.setBirthDay(new Date());

            // //////////////////////////////////////////////////////////
            System.out.println("----------简单对象之间的转化-------------");
            // 简单的bean转为json
            String s1 = gson.toJson(student1);
            System.out.println("简单Bean转化为Json===" + s1);

            // json转为简单Bean
            Student student = gson.fromJson(s1, Student.class);
            System.out.println("Json转为简单Bean===" + student);
            // //////////////////////////////////////////////////////////

            Student student2 = new Student();
            student2.setId(2);
            student2.setName("曹贵生");
            student2.setBirthDay(new Date());

            Student student3 = new Student();
            student3.setId(3);
            student3.setName("柳波");
            student3.setBirthDay(new Date());

            List<Student> list = new ArrayList<Student>();
            list.add(student1);
            list.add(student2);
            list.add(student3);

            System.out.println("----------带泛型的List之间的转化-------------");
            // 带泛型的list转化为json
            String s2 = gson.toJson(list);
            System.out.println("带泛型的list转化为json==" + s2);

            // json转为带泛型的list
            List<Student> retList = gson.fromJson(s2, new TypeToken<List<Student>>() {}.getType());
            for (Student stu : retList) {
                System.out.println(stu);
            }

        }
    }

    public static class GsonTest3 {
        public static void main(String[] args) {
            Gson gson = new GsonBuilder().enableComplexMapKeySerialization()
                    .create();

            Map<Point, String> map1 = new LinkedHashMap<Point, String>();// 使用LinkedHashMap将结果按先进先出顺序排列
            map1.put(new Point(5, 6), "a");
            map1.put(new Point(8, 8), "b");
            String s = gson.toJson(map1);
            System.out.println(s);// 结果:[[{"x":5,"y":6},"a"],[{"x":8,"y":8},"b"]]

            Map<Point, String> retMap = gson.fromJson(s,
                    new TypeToken<Map<Point, String>>() {
                    }.getType());
            for (Point p : retMap.keySet()) {
                System.out.println("key:" + p + " values:" + retMap.get(p));
            }
            System.out.println(retMap);

            System.out.println("----------------------------------");
            Map<String, Point> map2 = new LinkedHashMap<String, Point>();
            map2.put("a", new Point(3, 4));
            map2.put("b", new Point(5, 6));
            String s2 = gson.toJson(map2);
            System.out.println(s2);

            Map<String, Point> retMap2 = gson.fromJson(s2,
                    new TypeToken<Map<String, Point>>() {
                    }.getType());
            for (String key : retMap2.keySet()) {
                System.out.println("key:" + key + " values:" + retMap2.get(key));
            }

        }
    }

    public static class GsonTest4 {
        public static void main(String[] args) {
            Student student1 = new Student();
            student1.setId(1);
            student1.setName("李坤");
            student1.setBirthDay(new Date());

            Student student2 = new Student();
            student2.setId(2);
            student2.setName("曹贵生");
            student2.setBirthDay(new Date());

            Student student3 = new Student();
            student3.setId(3);
            student3.setName("柳波");
            student3.setBirthDay(new Date());

            List<Student> stulist = new ArrayList<Student>();
            stulist.add(student1);
            stulist.add(student2);
            stulist.add(student3);

            Teacher teacher1 = new Teacher();
            teacher1.setId(1);
            teacher1.setName("米老师");
            teacher1.setTitle("教授");

            Teacher teacher2 = new Teacher();
            teacher2.setId(2);
            teacher2.setName("丁老师");
            teacher2.setTitle("讲师");
            List<Teacher> teacherList = new ArrayList<Teacher>();
            teacherList.add(teacher1);
            teacherList.add(teacher2);

            Map<String, Object> map = new LinkedHashMap<String, Object>();
            map.put("students", stulist);
            map.put("teachers", teacherList);

            Gson gson = new Gson();
            String s = gson.toJson(map);
            System.out.println(s);

            System.out.println("----------------------------------");

            Map<String, Object> retMap = gson.fromJson(s,
                    new TypeToken<Map<String, List<Object>>>() {
                    }.getType());

            for (String key : retMap.keySet()) {
                System.out.println("key:" + key + " values:" + retMap.get(key));
                if (key.equals("students")) {
                    List<Student> stuList = (List<Student>) retMap.get(key);
                    System.out.println(stuList);
                } else if (key.equals("teachers")) {
                    List<Teacher> tchrList = (List<Teacher>) retMap.get(key);
                    System.out.println(tchrList);
                }
            }

        }
    }

    public static class GsonTest5 {
        public static void main(String[] args) {
            // 对象转为Json-->start
            Student student1 = new Student();
            student1.setId(1);
            student1.setName("李坤");
            student1.setBirthDay(new Date());

            Student student2 = new Student();
            student2.setId(2);
            student2.setName("曹贵生");
            student2.setBirthDay(new Date());

            Student student3 = new Student();
            student3.setId(3);
            student3.setName("柳波");
            student3.setBirthDay(new Date());

            List<Student> stulist = new ArrayList<Student>();
            stulist.add(student1);
            stulist.add(student2);
            stulist.add(student3);

            Teacher teacher1 = new Teacher();
            teacher1.setId(1);
            teacher1.setName("米老师");
            teacher1.setTitle("教授");

            Teacher teacher2 = new Teacher();
            teacher2.setId(2);
            teacher2.setName("丁老师");
            teacher2.setTitle("讲师");
            List<Teacher> teacherList = new ArrayList<Teacher>();
            teacherList.add(teacher1);
            teacherList.add(teacher2);

            TableData td1 = new TableData();
            td1.setTableName("students");
            td1.setTableData(stulist);

            TableData td2 = new TableData();
            td2.setTableName("teachers");
            td2.setTableData(teacherList);

            List<TableData> tdList = new ArrayList<TableData>();
            tdList.add(td1);
            tdList.add(td2);
            Gson gson = new Gson();
            String s = gson.toJson(tdList);

            System.out.println(s);
            // 结果:[{"tableName":"students","tableData":[{"id":1,"name":"李坤","birthDay":"Jun 22, 2012 10:44:16 AM"},{"id":2,"name":"曹贵生","birthDay":"Jun 22, 2012 10:44:16 AM"},{"id":3,"name":"柳波","birthDay":"Jun 22, 2012 10:44:16 AM"}]},{"tableName":"teachers","tableData":[{"id":1,"name":"米老师","title":"教授"},{"id":2,"name":"丁老师","title":"讲师"}]}]
            // 对象转为Json-->end

            // /////////////////////////////////////////////////////////////////////

            // 将json转为数据-->start
            List<TableData> tableDatas2 = gson.fromJson(s, new TypeToken<List<TableData>>() {}.getType());

            for (int i = 0; i < tableDatas2.size(); i++) {
                TableData entityData = tableDatas2.get(i);
                String tableName = entityData.getTableName();
                List tableData = entityData.getTableData();
                String s2 = gson.toJson(tableData);
                // System.out.println(s2);
                // System.out.println(entityData.getData());
                if (tableName.equals("students")) {
                    System.out.println("students");
                    List<Student> retStuList = gson.fromJson(s2, new TypeToken<List<Student>>() {}.getType());

                    for (int j = 0; j < retStuList.size(); j++) {
                        System.out.println(retStuList.get(j));
                    }

                } else if (tableName.equals("teachers")) {
                    System.out.println("teachers");
                    List<Teacher> retTchrList = gson.fromJson(s2, new TypeToken<List<Teacher>>() {}.getType());

                    for (int j = 0; j < retTchrList.size(); j++) {
                        System.out.println(retTchrList.get(j));
                    }
                }
            }

            // Json转为对象-->end
        }
    }

    public static class GsonTest6 {
        public static void main(String[] args) {
            GsonBuilder gsonBuilder = new GsonBuilder();
            gsonBuilder.registerTypeAdapter(PackageState.class,
                    new EnumSerializer());
            Gson gson = gsonBuilder.create();
            PackageItem item = new PackageItem();
            item.setName("item_name");
            item.setSize("500M");
            item.setState(PackageState.UPDATING);// 这个 state是枚举值

            String s = gson.toJson(item);
            System.out.println(s);

            System.out.println("--------------------------------");

            PackageItem retItem = gson.fromJson(s, PackageItem.class);
            System.out.println(retItem);
        }
    }

    public static class Point {
        private int x;
        private int y;

        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        @Override
        public String toString() {
            return "Point [x=" + x + ", y=" + y + "]";
        }
    }

    public static class Teacher {
        private int id;

        private String name;

        private String title;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        @Override
        public String toString() {
            return "Teacher [id=" + id + ", name=" + name + ", title=" + title
                    + "]";
        }
    }

    public static class PackageItem {
        private String name;
        private PackageState state;
        private String size;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public PackageState getState() {
            return state;
        }

        public void setState(PackageState state) {
            this.state = state;
        }

        public String getSize() {
            return size;
        }

        public void setSize(String size) {
            this.size = size;
        }

        @Override
        public String toString() {
            return "PackageItem [name=" + name + ", size=" + size + ", state="
                    + state + "]";
        }
    }

    public static class EnumSerializer implements JsonSerializer<PackageState>, JsonDeserializer<PackageState> {

        // 对象转为Json时调用,实现JsonSerializer<PackageState>接口
        @Override
        public JsonElement serialize(PackageState state, Type arg1,
                                     JsonSerializationContext arg2) {
            return new JsonPrimitive(state.ordinal());
        }

        // json转为对象时调用,实现JsonDeserializer<PackageState>接口
        @Override
        public PackageState deserialize(JsonElement json, Type typeOfT,
                                        JsonDeserializationContext context) throws JsonParseException {
            if (json.getAsInt() < PackageState.values().length)
                return PackageState.values()[json.getAsInt()];
            return null;
        }

    }

    public enum  PackageState {
        PLAY, UPDATE, UPDATING, DOWNLOAD, DOWNLOADING,
    }

    public static class TableData {
        private String tableName;

        private List tableData;

        public String getTableName() {
            return tableName;
        }

        public void setTableName(String tableName) {
            this.tableName = tableName;
        }

        public List getTableData() {
            return tableData;
        }

        public void setTableData(List tableData) {
            this.tableData = tableData;
        }
    }

    public static class Student {
        private int id;

        @Expose
        private String name;

        @Expose
        @SerializedName("bir")
        private Date birthDay;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Date getBirthDay() {
            return birthDay;
        }

        public void setBirthDay(Date birthDay) {
            this.birthDay = birthDay;
        }

        @Override
        public String toString() {
            return "Student [birthDay=" + birthDay + ", id=" + id + ", name="
                    + name + "]";
        }

    }
}
